package com.htjc.uep.center.acct.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;

/**
 * Created on 2008-4-12
 * <p>Description: [日期公用类]</p>
 */
public final class DateUtil
{
	private DateUtil()
	{
	}

	public static final long MILLIS_PER_DAY = 1000 * 60 * 60 * 24;

	public final static long MILLIS_PER_HOUR = 1000 * 60 * 60 * 1;

	public static final String DATE_YYYYMM = "yyyyMM";

	public static final String DATE_YYYYMMDD = "yyyyMMdd";

	public static final String DATE_YYYY_MM_DD = "yyyy/MM/dd";

	public static final String DATE_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

	public static final String DATE_YYYY_MM_DD_HH_MM_SS = "yyyy/MM/dd HH:mm:ss";

	/**
	 * <p>Discription:[本服务中特有的时间格式]</p>
	 * @return
	 */
	public static String currentTime()
	{
		//获取当前系统的时间，指定日期格式化
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_YYYYMMDDHHMMSS);
		return dateFormat.format(new java.util.Date()); //转为字符串
	}

	public static String current_Time()
	{
		//获取当前系统的时间，指定日期格式化
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_YYYY_MM_DD_HH_MM_SS);
		return dateFormat.format(new java.util.Date()); //转为字符串
	}

	public static String currentDay()
	{
		//获取当前系统的时间，指定日期格式化
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_YYYYMMDD);
		return dateFormat.format(new java.util.Date()); //转为字符串
	}

	public static String currentYM()
	{
		//获取当前系统的时间，指定日期格式化
		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_YYYYMM);
		return dateFormat.format(new java.util.Date()); //转为字符串
	}

	/**取每月最后一天**/
	public static Date lastOfYMDay(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
		calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), 1, 23, 59, 59);
		calendar.roll(Calendar.DATE, -1);
		return calendar.getTime();
	}

	/**取每年最后一天**/
	public static Date lastOfYearDay(Date date)
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(calendar.get(Calendar.YEAR), 11, 1, 23, 59, 59);
		calendar.roll(Calendar.DATE, -1);
		return calendar.getTime();
	}

	/**
	 * <p>Discription:[日期格式化，默认返回YYYYMMDD]</p>
	 * @param date
	 * @return
	 */
	public static String formatDate(long date, String format)
	{
		SimpleDateFormat dateFormat = new SimpleDateFormat(format);
		return dateFormat.format(date); //指定日期格式化，转为字符串
	}

	/**
	 * <p>Discription:[按指定格式解析日期]</p>
	 * @param date
	 * @param format
	 * @return
	 * @throws ParseException
	 */
	public static Date parseDate(String date, String format) throws ParseException
	{
		return new SimpleDateFormat(format).parse(date);
	}

	/**
	 * <p>Discription:[获取下一个日期的零点]</p>
	 */
	public static Date getNextTime() throws ParseException
	{
		return getAddDays(parseDate(currentDay(), DATE_YYYYMMDD), 1);
	}

	/**
	 * <p>Discription:[取得指定月份若干月后的月份]</p>
	 * @param strDate 格式 yyyyMM
	 * @param monthCount
	 * @return
	 */
	public static String getAddMonth(String strDate, int monthCount)
	{
		java.util.Calendar c = Calendar.getInstance();
		int year = Integer.parseInt(strDate.substring(0, 4));
		int month = Integer.parseInt(strDate.substring(4, 6));
		c.set(year, month, 0);
		c.add(Calendar.MONTH, monthCount);
		return new SimpleDateFormat("yyyyMM").format(c.getTime());
	}

	/**
	 * <p>Discription:[取得某年的若干年后时间]</p>
	 * @param date
	 * @param years
	 * @return
	 */
	public static Date getAddYears(Date date, int years)
	{
		return add(date, Calendar.YEAR, years);
	}

	/**
	 * <p>Discription:[取得某月的若干月后时间]</p>
	 * @param date
	 * @param months
	 * @return
	 */
	public static Date getAddMonths(Date date, int months)
	{
		return add(date, Calendar.MONTH, months);
	}

	/**
	 * <p>Discription:[取得某天的若干天后时间]</p>
	 * @param date
	 * @param days
	 * @return
	 */
	public static Date getAddDays(Date date, int days)
	{
		return add(date, Calendar.DAY_OF_MONTH, days);
	}

	/**
	 * <p>Discription:[取得某小时的若干小时后时间]</p>
	 * @param date
	 * @param hours
	 * @return
	 */
	public static Date getAddHours(Date date, int hours)
	{
		return add(date, Calendar.HOUR_OF_DAY, hours);
	}

	/**
	 * <p>Discription:[取得某分钟的若干分钟后时间]</p>
	 * @param date
	 * @param minutes
	 * @return
	 */
	public static Date getAddMinutes(Date date, int minutes)
	{
		return add(date, Calendar.MINUTE, minutes);
	}

	/**
	 * <p>Discription:[取得某秒的若干秒后时间]</p>
	 * @param date
	 * @param seconds
	 * @return
	 */
	public static Date getAddSeconds(Date date, int seconds)
	{
		return add(date, Calendar.SECOND, seconds);
	}

	public static Date add(Date date, int calendarField, int amount)
	{
		if (date == null)
		{
			throw new IllegalArgumentException("The date must not be null");
		}
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(calendarField, amount);
		return c.getTime();
	}

	/**
	 * <p>Discription:[随机生成日期，格式YYYYMMDD]</p>
	 * @param beginDate
	 * @param endDate
	 * @return
	 */
	public static long randomDate(String beginDate, String endDate)
	{
		try
		{
			SimpleDateFormat format = new SimpleDateFormat(DateUtil.DATE_YYYYMMDD);
			Date start = format.parse(beginDate);// 开始日期
			Date end = format.parse(endDate);// 结束日期
			if (start.getTime() >= end.getTime())
			{
				throw new IllegalArgumentException("随机日期生成参数有误，请确认后再次请求。");
			}
			return random(start.getTime(), end.getTime());
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return 0;
		}
	}

	/**
	 * <p>Discription:[Random number]</p>
	 * @param begin
	 * @param end
	 * @return
	 */
	private static long random(long begin, long end)
	{
		long random = begin + (long) (Math.random() * (end - begin));
		if (random == begin || random == end)
		{
			return random(begin, end);
		}
		return random;
	}

	/**
	* @Description:判断<firstDate>时间点是否在<secondDate>时间点之前
	* 如果此 firstDate 的时间在参数<secondDate>表示的时间之前，则返回小于 0 的值
	* @param firstDate
	* @param secondDate
	* @return
	* @ReturnType boolean
	*/
	public static boolean isBefore(Date firstDate, Date secondDate)
	{
		return compare(firstDate, secondDate) < 0 ? true : false;
	}

	/**
	* @Description:判断<firstDate>时间点是否在<secondDate>时间点之后
	* 如果此 firstDate 的时间在参数<secondDate>表示的时间之后，则返回大于 0 的值
	* @param firstDate
	* @param secondDate 
	* @ReturnType boolean
	*/
	public static boolean isAfter(Date firstDate, Date secondDate)
	{
		return compare(firstDate, secondDate) > 0 ? true : false;
	}

	/**
	* @Description:比较两个时间点
	* 如果secondDate表示的时间等于此 firstDate 表示的时间，则返回 0 值；
	* 如果此 firstDate 的时间在参数<secondDate>表示的时间之前，则返回小于 0 的值；
	* 如果此 firstDate 的时间在参数<secondDate>表示的时间之后，则返回大于 0 的值
	* @param firstDate
	* @param secondDate
	* @ReturnType int
	*/
	private static int compare(Date firstDate, Date secondDate)
	{
		Calendar firstCalendar = null;
		/**使用给定的 Date 设置此 Calendar 的时间。**/
		if (firstDate != null)
		{
			firstCalendar = Calendar.getInstance();
			firstCalendar.setTime(firstDate);
		}

		Calendar secondCalendar = null;
		/**使用给定的 Date 设置此 Calendar 的时间。**/
		if (secondDate != null)
		{
			secondCalendar = Calendar.getInstance();
			secondCalendar.setTime(secondDate);
		}

		try
		{
			/**
			* 比较两个 Calendar 对象表示的时间值（从历元至现在的毫秒偏移量）。
			* 如果参数表示的时间等于此 Calendar 表示的时间，则返回 0 值；
			* 如果此 Calendar 的时间在参数表示的时间之前，则返回小于 0 的值；
			* 如果此 Calendar 的时间在参数表示的时间之后，则返回大于 0 的值
			* **/
			return firstCalendar.compareTo(secondCalendar);
		}
		catch (NullPointerException e)
		{
			throw new IllegalArgumentException(e);
		}
		catch (IllegalArgumentException e)
		{
			throw new IllegalArgumentException(e);
		}
	}

	/**
	* @Description:
	* @param startDate
	* @param endDate
	* @param inDate
	* @return
	* @ReturnType boolean
	*/
	public static boolean isBetween(Date startDate, Date endDate, Date inDate)
	{
		/**
		* 判断<endDate>时间点是否在<startDate>时间点之前
		* 如果为真表示<endDate>时间点在<startDate>时间点之前则抛出异常
		* 即结束时间在开始时间之前是不正常的
		*/
		if (isBefore(endDate, startDate))
		{
			throw new IllegalArgumentException("endDate can not before startDate!");
		}

		/**
		* 比较两个时间点<inDate>和<startDate>
		 * 如果inDate表示的时间等于此 startDate 表示的时间，则返回 0 值；
		 * 如果此 inDate 的时间在参数<startDate>表示的时间之前，则返回小于 0 的值；
		 * 如果此 inDate 的时间在参数<startDate>表示的时间之后，则返回大于 0 的值
		*/
		int startFlag = compare(inDate, startDate);

		/**
		* 比较两个时间点<inDate>和<endDate>
		 * 如果inDate表示的时间等于此 endDate 表示的时间，则返回 0 值；
		 * 如果此 inDate 的时间在参数<endDate>表示的时间之前，则返回小于 0 的值；
		 * 如果此 inDate 的时间在参数<endDate>表示的时间之后，则返回大于 0 的值
		*/
		int endFlag = compare(inDate, endDate);

		/**满足-inDate 的时间在参数<startDate>表示的时间之后**/
		/**满足-inDate 的时间在参数<endDate>表示的时间之前**/
		/**一个日期在一个日期区间之内**/
		return (startFlag >= 0 && endFlag <= 0) ? true : false;
	}
	
	public static XMLGregorianCalendar currentXMLGregorianCalendar()
	{

		GregorianCalendar cal = new GregorianCalendar();
		cal.set(GregorianCalendar.MILLISECOND, 0);
		XMLGregorianCalendar gc = null;
		try
		{
			gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
		}
		catch (Exception e)
		{

			e.printStackTrace();
		}
		return gc;
	}

	public static XMLGregorianCalendar convertToXMLGregorianCalendar(final long date)
	{

		final GregorianCalendar cal = new GregorianCalendar();
		cal.setTimeInMillis(date);
		XMLGregorianCalendar gc = null;
		try
		{
			gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
		}
		catch (Exception e)
		{

			e.printStackTrace();
		}
		return gc;
	}

	public static Date convertToDate(XMLGregorianCalendar cal) throws Exception
	{
		GregorianCalendar ca = cal.toGregorianCalendar();
		return ca.getTime();
	}
}